package main

import (
	"context"
	"database/sql"
	"fmt"
	_ "github.com/go-sql-driver/mysql" // lint: mysql driver.
	"github.com/kataras/iris/v12"
	"github.com/kataras/iris/v12/middleware/basicauth"

	"os"
)

// struct值必须包含Username和Passwords字段
//或GetUsername（）字符串和GetPassword（）字符串方法。
type Auth_info struct {
	ID   int64  `db:"id" json:"id"`
	Username  string `db:"username" json:"username"`
	Password  string `db:"password" json:"password"`
}
type database struct {
	*sql.DB
}


func (A Auth_info) GetUsername() string {
	return A.Username
}
func (A Auth_info) GetPassword() string {
	return A.Username
}
func getenv(key string, def string) string {
	v := os.Getenv(key)
	if v == "" {
		return def
	}

	return v
}
func connect(dsn string) (*database, error) {
	conn, err := sql.Open("mysql", dsn)
	if err != nil {
		return nil, err
	}
	err = conn.Ping()
	if err != nil {
		conn.Close()
		return nil, err
	}

	return &database{conn}, nil
}

func GetUserInfo()basicauth.Options {
	dsn := fmt.Sprintf("%s:%s@tcp(%s:3306)/%s?parseTime=true&charset=utf8mb4&collation=utf8mb4_unicode_ci",
		getenv("MYSQL_USER", "root"),
		getenv("MYSQL_PASSWORD", "123321"),
		getenv("MYSQL_HOST", "localhost"),
		getenv("MYSQL_DATABASE", "tonicgb"),
	)
	db, err := connect(dsn)
	if err != nil {
		panic(err)
	}

	// Validate a user from database.
	allowFunc := func(ctx iris.Context, username, password string) (interface{}, bool) {
		user, err := db.getUserByUsernameAndPassword(context.Background(), username, password)
		return user, err == nil
	}
	opts := basicauth.Options{
		Realm:        basicauth.DefaultRealm,
		ErrorHandler: basicauth.DefaultErrorHandler,
		Allow:        allowFunc,
	}

	return opts
}
/**
查询数据
 */
func (db *database) getUserByUsernameAndPassword(ctx context.Context, username, password string) (Auth_info, error) {
	query := fmt.Sprintf("SELECT id,admin_name,admin_password FROM %s WHERE %s = ? AND %s = ? LIMIT 1", "admins", "admin_name", "admin_password")
	rows, err := db.QueryContext(ctx, query, username, password)
	if err != nil {
		return Auth_info{}, err
	}
	defer rows.Close()
	if !rows.Next() {
		return Auth_info{}, sql.ErrNoRows
	}

	var user Auth_info
	err = rows.Scan(&user.ID, &user.Username, &user.Password)
	return user, err
}

func newApp() *iris.Application {
	app := iris.New()
	auth := basicauth.New(GetUserInfo())

	app.Get("/test",auth,test)
	//到全局app.Use（auth）（或app.UseGlobal在.Run之前）
	//进行路由

	app.Get("/", func(ctx iris.Context) { ctx.Redirect("/admin") })

	// to party

	needAuth := app.Party("/admin", auth)
	{
		//http://localhost:8080/admin
		needAuth.Get("/", handler)
		// http://localhost:8080/admin/profile
		needAuth.Get("/profile", handler)

		// http://localhost:8080/admin/settings
		needAuth.Get("/settings", handler)

		needAuth.Get("/logout", logout)
	}

	return app
}

func main()  {
	app := newApp()

	app.Run(iris.Addr(":8080"))
}
func test(ctx iris.Context)  {
	ctx.WriteString("fuckyou")
}
func routeHandler(ctx iris.Context) {
	fmt.Println("caonima")
	username, password, _ := ctx.Request().BasicAuth()

	// user.Username
	// user.Password
	ctx.WriteString(username+password)
}
func handler(ctx iris.Context) {
	user_name,pwd,_:=ctx.Request().BasicAuth()
	ctx.WriteString(user_name+"fuck"+pwd)
	//用户名，密码，_：= ctx.Request().BasicAuth（）//第三个参数将始终为true，因为中间件对此进行了确保，否则将不执行该处理程序。 // 要么：
	user := ctx.User()
	// 或ctx.User（）.GetRaw（）获取下划线值。
	username, _ := user.GetUsername()
	password, _ := user.GetPassword()
	ctx.Writef("%s %s:%s", ctx.Path(), username, password)
}

func logout(ctx iris.Context) {
	err := ctx.Logout() // fires 401, invalidates the basic auth.
	if err != nil {
		ctx.Application().Logger().Errorf("Logout error: %v", err)
	}
	ctx.Redirect("/admin", iris.StatusTemporaryRedirect)
}